#!/usr/local/bin/python
# Rob Dennis  Lurchington Q. Delacroix
# Keasby - TV renamer
# Project Homepage: http://code.google.com/p/keasby/

from os.path import join as pjoin
from xml.dom import minidom
from keasby_toolbox import dump_zip

class XmlHandler():
    def __init__(self,default_dir=""):
        """
        Handles XML interaction tasks
        """

        self._dom = {}
        self.default_dir = default_dir

#---Parse XML Dom

    def parse_xml_string(self, key, string):
        """
        Handles a string
        """

        self[key] = minidom.parseString(string)

        return self[key]

    def parse_xml_path(self, key, path=None):
        """
        Opens a file object, then passes to parse_xml_obj
        """

        if path is None:
            path = key

        self.parse_xml_obj(key,open(path,"rb"))

        return self[key]

    def parse_xml_obj(self, key, file_obj):
        """
        Parses using a file object, then closes that object
        """

        self[key] = minidom.parse(file_obj)

        file_obj.close()

        return self[key]

    def parse_zipfile(self, key, path, subfile):
        """
        Parses the contents of the subfile in the given zipfile
        path
        """

        return self.parse_xml_string(key,dump_zip(path,subfile))

#---Operator

    def __setitem__(self, key, dom):
        """
        Places the parsed XML file in dict
        """

        self._dom[key] = DomWrapper(dom)

    def __getitem__(self, key):

        try:
            if key not in self._dom:
                self.parse_xml_path(key,pjoin(self.default_dir,key))
        except Exception, error_message:
            raise TvDbCacheError("unable to find key name: %s"%key +
                                    " : %s"%error_message)

        return self._dom[key]


class DomWrapper():
    """
    Lightweight wrapper to get interact with the DOM with bracket syntax
    """

    def __init__(self, dom):

        if dom is None:
            logging.warning("unable to get elements for empty XML DOM")
            raise TvDbXmlHandlerError("Empty XML DOM")

        self.dom = dom
        try:
            self.attributes = self.dom.attributes
        except Exception:
            #it's most likely a NodeList if there's no attributes
            pass

#---Operator

    def __getitem__(self, tagname):
        """
        Convenience function for returning all the data for
        a given tagname
        """

        return map(DomWrapper,self.dom.getElementsByTagName(tagname))

    def __str__(self):
        """
        String representation
        """

        return self.dom.toxml()

#---Utility

    def get_array(self, array_key, item_keys, optional_keys=[]):
        """
        Returns the array of all the elements in a DOM with tag <array_key>
        with each item in the array being a dictionary with keys consisting
        of item_keys
        """

        temp_array = []

        for block in self[array_key]:
            temp_dict = {}

            for item in item_keys:
                try:
                    temp_dict[item] = block[item][0].data()
                except IndexError:
                    raise TvDbXmlHandlerError("Required key: %s"%item+
                                                " not found in %s"%block)
                except Exception:
                    raise TvDbXmlHandlerError("unknown error finding: %s"%item+
                                                " in %s"%block)

            for optional_item in optional_keys:
                try:
                    temp_dict[optional_item] = block[optional_item][0].data()
                except IndexError:
                    pass

            temp_array.append(temp_dict)

        return temp_array


    def data(self):
        """
        data from the DOM
        """
        if self.dom.firstChild is None:
            return None

        return self.dom.firstChild.data